#include <sstream>
#include <SypX/Font.h>

#ifdef SYPX_MEMCHECK
#include "mmgr.h"
#endif

#include "GameScene.h"
#include "MissionScene.h"
#include "SheepDefenceApp.h"
#include "Level.h"

namespace SheepDefence
{
	GameScene::GameScene(SypX::Font* f, int level, int breed, int highscore):cumTime(0),counter(0),fps(0),lvl(level), breed(breed), highscore(highscore)
	{
		font = f;				
	}

	GameScene::~GameScene(void)
	{	
		delete level;
		delete tBox;
		engine->getAudioEngine()->stopMusic();
	}

	void GameScene::init()
	{
		engine = SypX::Engine::getSingleton();
		render = engine->getRenderer();
		canvas = engine->getCanvas();
		render->setClearScreenColor(SypX::Vec4(0.0f,0.0f,0.0f,1.0f));	

		tBox = new SypX::TextBox(font, 200.0f, 150.0f, 5);
		tBox->setBgColor(SypX::Vec4(0, 0, 0, 1.0f));
		tBox->setBorderColor(SypX::Vec4(1.0f, 1.0f, 1.0f, 1.0f));		
		tBox->getMeshInstance()->setPosition(SypX::Vec3(160.0f, 260.0f, 1.1f));		

		if(!font)
		{
			font = engine->loadFontFromFile("Fonts/sheepFont.ttf", 24, 3);
		}

		std::ostringstream oss;
		oss << "Levels/" << lvl << ".lvl";

		switch (breed)
		{
		case 0:
			level = new Level(font, oss.str(), TERRIER);
			break;
		case 1:
			level = new Level(font, oss.str(), COLLIE);
			break;
		case 2:
			level = new Level(font, oss.str(), GREYHOUND);
			break;
		}

		mouseDown = false;
		engine->getAudioEngine()->playMusic("Sounds/song.mp3");
		
	}
	
	void GameScene::calcAndDrawFPS()
	{
		++counter;
		if(cumTime > 1.0f)
		{
			fps = counter;
			cumTime = 0;
			counter = 0;			
		}
		
		std::ostringstream oss;
		oss << fps << " FPS";		
		font->drawText(oss.str(), 10.0f, 430.0f, 1.0f);
		render->setActiveColor(SypX::Vec4(1.0f,1.0f,1.0f, 0.85f));
		font->drawBufferedInstances();
	}

	void GameScene::run()
	{
		float time;
		
		render->clearScreen();
		handleInput();

		time = canvas->getElapsedTime();
		cumTime += time;
		
		float factor;
		std::ostringstream oss;
		switch(level->state)
		{
		case GAMEOVER:
			render->setActiveColor(SypX::Vec4(1.0f,1.0f,1.0f, 1.0f));
			tBox->setText("    GAME OVER");
			tBox->draw();
			if(level->stateAge > 5.0f)
			{
				changeScene(new MissionScene(font, lvl));
			}
			factor = level->stateAge / 3.0f;
			if(factor > 1.0f)
				factor = 1.0f;
			render->setActiveColor(SypX::Vec4(1.0f ,1.0f - factor, 1.0f - factor, 1.0f));
			break;
		case WIN:		
			oss<<"     YOU WIN!\n";			
			if (level->score > highscore)
				oss << "NEW HIGH ";
			oss << "SCORE: " << level->score<<"\n";
			/*if (level->score > highscore)
				font->drawText(oss.str(), 70.0f, 240.0f, 1.0f);			
			else
				font->drawText(oss.str(), 120.0f, 240.0f, 1.0f);			
			oss.clear();
			oss.str("");*/
			oss << "GRADE: ";
			for (int i = 0; i < level->stars; i++)
				oss << "*";
			tBox->setText(oss.str());
			tBox->draw();		
			if(level->stateAge > 5.0f)
			{
				changeScene(new MissionScene(font, lvl, breed, level->score, level->stars));
			}
			factor = level->stateAge / 3.0f;
			if(factor > 1.0f)
				factor = 1.0f;
			render->setActiveColor(SypX::Vec4(1.0f - factor, 1.0f, 1.0f - factor, 1.0f));
			break;
		case BRIEFING:
		case INPROGRESS:
			render->setActiveColor(SypX::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
			break;
		}
		
		level->draw();
		level->act(time);
		level->advance(time);
		calcAndDrawFPS();
		canvas->swapBuffers();
	}

	void GameScene::handleInput()
	{
		SypX::Event e, nextEvent = SypX::Event();
		nextEvent.type = SypX::NOEVENTS;
		bool breakOut = false;

		while (true)
		{
			if (nextEvent.type == SypX::NOEVENTS)
				e = canvas->getEvent();
			else
			{
				e = nextEvent;
				nextEvent.type = SypX::NOEVENTS;
			}

			switch (e.type)
			{
			case SypX::TOUCHDOWN:
			case SypX::MOUSELEFTDOWN:
				level->move((float) e.location.x, (float) e.location.y);				
				mouseDown = true;
				if (breakOut) return;
				break;
			case SypX::TOUCHUP:
			case SypX::MOUSELEFTUP:
				mouseDown = false;
				if (breakOut) return;
				break;
			case SypX::TOUCHMOVE:
			case SypX::MOUSEMOVE:
				if (mouseDown)
				{
					nextEvent = canvas->getEvent();
					while (nextEvent.type == SypX::MOUSEMOVE || nextEvent.type == SypX::TOUCHMOVE)
					{
						e = nextEvent;
						nextEvent = canvas->getEvent();
					}

					level->move((float) e.moved.curr.x, (float) e.moved.curr.y);
					if (breakOut) return;
					breakOut = true;
				}
				break;
			case SypX::NOEVENTS:
				return;
			default:
				break;
			}
		}
	}
}